feat(deploy): pull the released image in the NPM overlay instead of building#30
Merged
Merged
Conversation
…uilding
CI publishes an attested, digest-addressable image to ghcr.io/berntpopp/stringdb-link
on every release. But the deployed compose chain never consumed it.
stringdb-link deploys as `docker-compose.yml -f docker-compose.npm.yml`, and the NPM
file is a PURE OVERLAY: it declares neither `build:` nor `image:`, so it inherited the
base file's `build:` block. Every deploy therefore rebuilt the image from source on the
server, and the published, attested image was dead weight. Confirmed on the VPS:
stringdb_link_server currently runs `stringdb-link-npm-stringdb-link` — a locally built
image, not the GHCR release.
The overlay now pulls the release:
build: !reset null
image: ${STRINGDB_LINK_IMAGE:?...}
pull_policy: missing
`build: !reset null` is mandatory here. Unlike a self-contained overlay, adding only
`image:` would leave the base's `build:` in the merged model and Compose would still
consider the service buildable. It fails closed when the pin is unset, matching the
contract docker-compose.prod.yml already uses. A digest is required rather than a tag:
no `latest` tag is published, and only a digest is immutable.
Deliberately unchanged: `container_name` (stringdb_link_server — NPM's proxy_pass
resolves the container name, so renaming it would 502 the public host), the Compose
project name (stringdb-link-npm — renaming it would rename named volumes), the
healthcheck and its start_period, the read-only/cap-drop hardening block, the networks
and the `command`.
Verified by rendering the actual deployed chain:
$ docker compose -f docker/docker-compose.yml -f docker/docker-compose.npm.yml config
required variable STRINGDB_LINK_IMAGE is missing a value # fails closed
$ STRINGDB_LINK_IMAGE=...@sha256:... docker compose ... config
image: ghcr.io/berntpopp/stringdb-link@sha256:...
container_name: stringdb_link_server
# no `build:` key anywhere in the rendered model — the server cannot build
Also adds STRINGDB_LINK_IMAGE to .env.docker.example (it was documented nowhere an
operator would copy) and bumps to 4.0.6 to cut a release carrying the fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Zn3DVmcCxo58ujjJjmmfa
`uv.lock` records the project's own version, so bumping [project].version leaves it stale. The container-CI gate runs `uv lock --check` and fails closed on it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Zn3DVmcCxo58ujjJjmmfa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
CI publishes an attested, digest-addressable image to
ghcr.io/berntpopp/stringdb-linkonevery release. The deployed compose chain never consumed it.
stringdb-link deploys as
docker-compose.yml -f docker-compose.npm.yml, and the NPM fileis a pure overlay: it declares neither
build:norimage:, so it inherited the basefile's
build:block. Every deploy rebuilt the image from source on the server, and thepublished, attested image was dead weight.
Confirmed on the VPS —
stringdb_link_serveris currently runningstringdb-link-npm-stringdb-link, a locally built image, not the GHCR release.Change
docker/docker-compose.npm.ymlnow pulls the released image:build: !reset nullis mandatory here. Unlike a self-contained overlay, adding onlyimage:would leave the base file'sbuild:in the merged model and Compose would stillconsider the service buildable. The pin fails closed when unset, matching the contract
docker-compose.prod.ymlalready uses. A digest is required rather than a tag: nolatesttag is published, and only a digest is immutable.
What deliberately did NOT change
container_name(stringdb_link_server) — NPM'sproxy_passresolves the containername, so renaming it would 502 the public host.
stringdb-link-npm) — renaming it renames named volumes.start_period), the read-only rootfs /cap_drop: ALLhardening block, the networks and the
command.Validation
Rendered against the actual deployed chain:
Also adds
STRINGDB_LINK_IMAGEto.env.docker.example(it was documented nowhere anoperator would copy) and bumps to 4.0.6 to cut a release carrying the fix.
🤖 Generated with Claude Code
https://claude.ai/code/session_011Zn3DVmcCxo58ujjJjmmfa